/*
 * ObjectUtil.java        1.0     2009-6-24  17:10:21
 *
 * Copyright (c) 2004, 2005 Works Systems, Inc.
 * Copyright (c) 2004, 2005 Works Systems (Tianjin) Co., Ltd.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * Works Systems, Inc and Works Systems (Tianjin) Co., Ltd. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with Works Systems.
 */
package com.microwintech.boardingtreasure.util;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;

/**
 * Created by IntelliJ IDEA. User: Chris.F Date: 2009-6-24 Time: 17:10:21
 */
public final class ObjectUtil {

	public static boolean equals(Object obj1, Object obj2) {
		if (obj1 == obj2)
			return true;
		if (obj1 == null || obj2 == null)
			return false;
		return obj1.equals(obj2);
	}

	public static boolean notEquals(Object obj1, Object obj2) {
		return !equals(obj1, obj2);
	}

	public static <E> boolean equals(Collection<E> obj1, Collection<E> obj2) {
		if (obj1 == obj2)
			return true;
		if (obj1 == null || obj2 == null)
			return false;
		if (obj1.size() != obj2.size())
			return false;

		Iterator<E> it1 = obj1.iterator();
		Iterator<E> it2 = obj2.iterator();
		while (it1.hasNext() && it2.hasNext()) {
			if (!equals(it1.next(), it2.next()))
				return false;
		}
		return true;
	}

	public static <E> boolean notEquals(Collection<E> obj1, Collection<E> obj2) {
		return !equals(obj1, obj2);
	}

	public static Object invoke(final Object obj, final String methodName, final Class<?>[] parameterTypes, final Object... args) {
		if (obj == null)
			return null;
		try {
			Method m = obj.getClass().getMethod(methodName, parameterTypes);
			return m.invoke(obj, args);
		} catch (InvocationTargetException e) {
			throw new RuntimeException(String.format("invoke method %s of class %s error", methodName, obj.getClass().getName()), e.getCause());
		} catch (Exception e) {
			System.err.println("invoke method error");
			e.printStackTrace(System.err);
		}
		return null;
	}

	public static Object getProperty(final Object obj, String expression) {
		if (obj == null)
			return null;
		String[] properties = StringUtil.split(expression, "\\.");
		if (properties.length == 0)
			return null;
		Object o = obj;
		try {
			for (String property : properties) {
				if (o == null)
					return null;
				String methodName = buildGet(property);
				o = invoke(o, methodName, new Class[0], new Object[0]);
			}
		} catch (Exception e) {
			System.err.println("invoke method error");
			e.printStackTrace(System.err);
			return null;
		}
		return o;
	}

	public static <T> void setProperty(final Object obj, String expression, Class c, T value) {
		if (obj == null)
			return;
		if (StringUtil.isEmpty(expression))
			return;

		Object o = obj;
		String property = expression;

		int pos = expression.lastIndexOf(".");
		if (pos != -1) {
			o = getProperty(obj, expression.substring(0, pos));
			property = expression.substring(pos + 1);
		}
		try {
			String methodName = buildSet(property);
			invoke(o, methodName, new Class[] { c }, value);
		} catch (Exception e) {
			System.err.println("invoke method error");
			e.printStackTrace(System.err);
		}
	}

	private static String buildSet(String property) {
		return "set" + property.substring(0, 1).toUpperCase() + property.substring(1);
	}

	private static String buildGet(String property) {
		return "get" + property.substring(0, 1).toUpperCase() + property.substring(1);
	}

}
